#!/usr/bin/env python
###############################################################################
# File: views.py
# Name: Sal Fuentes Jr.
# Date: 09/06/2008
# Info: This module includes the views that determine *WHAT* data gets displayed
###############################################################################
import os
import logging
import time

from google.appengine.api import users, urlfetch
from google.appengine.ext.webapp import template, RequestHandler
from models import AWSModel

class MyBaseReqHandler(RequestHandler):
  def get_template_path(self, template_filename):
    template_dir = os.path.join(os.path.dirname(__file__), '..', 'templates')
    return os.path.join(template_dir, template_filename)
    
  def dump(self, obj):
    obj_state = obj.__dict__
    dump_str = "\n" + "\n".join([ "obj.%s = %s" % (attr, value) for attr, value in obj_state.iteritems()]) + "\n"
    logging.debug("DEBUG: OBJ DUMP" + dump_str)
    
    #for attr, value in obj_state.iteritems():
      #logging.debug("obj.%s = %s" % (attr, value))
      
    #for attr in dir(obj):
      #logging.debug("obj.%s = %s" % (attr, getattr(obj, attr)))    

class IndexHandler(MyBaseReqHandler):
  def get(self):
    aws_access_key_id = self.request.get('awsAccessKeyId')
    aws_secret_access_key = self.request.get('awsSecretKey')
    aws_model = AWSModel(aws_access_key_id, aws_secret_access_key)
    
    buckets = ''
    if aws_secret_access_key:
      buckets = aws_model.get_data("buckets")
    template_data = { 'buckets': buckets }
    template_path = self.get_template_path('raw.html')
    
    self.response.out.write(template.render(template_path, template_data))

class AboutHandler(MyBaseReqHandler):
  def get(self):
    template_data = {}
    template_path = self.get_template_path('about.html')
    self.response.out.write(template.render(template_path, template_data))
        
class S3FoxViewHandler(MyBaseReqHandler):
  def get(self):
    aws_access_key_id = self.request.get('awsAccessKeyId')
    aws_secret_access_key = self.request.get('awsSecretKey')
    aws_model = AWSModel(aws_access_key_id, aws_secret_access_key)
      
    buckets = aws_model.get_data("buckets")
    template_data = { 'buckets': buckets }
    template_path = self.get_template_path('s3fox.html')
    
    self.response.out.write(template.render(template_path, template_data)) 

class GetBucketsHandler(MyBaseReqHandler):       
  def post(self):
    aws_access_key_id = self.request.get('awsAccessKeyId')
    aws_secret_access_key = self.request.get('awsSecretKey')
    aws_model = AWSModel(aws_access_key_id, aws_secret_access_key)  
    s3fox_view = self.request.get('view')
    
    buckets = aws_model.get_data("buckets")
    json_list = []
    bucket_list = []
    
    if s3fox_view:
      for bucket in buckets:
        bucket_name = bucket.name
        objs = aws_model.get_data("keys", bucket_name)
        
        bucket_tree = {}
        for obj in objs:
          key_name = obj.key
          if key_name.endswith('_$folder$'):
            virtual_folder = key_name.replace('_$folder$', '')
            #logging.debug('add2tree=%s' % virtual_folder)
            self.place_in_tree(bucket_tree, virtual_folder)
        
        logging.debug('buckettree=%s' % bucket_tree)                
        logging.debug('REDDDDDDDDDDDDDDDDDDDDD FLAG!!!!!!!!!!!!!!!!!')                
        key_list = self.generate_json_from_tree(bucket_tree)
        bucket_list.append("""
          {"id": "%s", "text": "%s",
          "children": [%s],
          "iconCls": "ibucket"}""" % (bucket_name, bucket_name, key_list))
    else:
      for bucket in buckets:
        bucket_name = bucket.name
        bucket_list.append('{"id": "%s", "text": "%s", "leaf": true, "iconCls": "ibucket"}' % (bucket_name, bucket_name))
        #self.dump(bucket)
      
    logging.debug('2REDDDDDDDDDDDDDDDDDDDDD FLAG!!!!!!!!!!!!!!!!!')                
    bucket_list_str = ','.join(bucket_list)
    json_list.append("[")
    json_list.append(bucket_list_str)
    json_list.append("]")        
    json_str = ''.join(json_list)
  
    self.response.headers.add_header("Content-Type", 'application/json')
    self.response.out.write(json_str)
  
  def generate_json_from_tree(self, node):
    """Returns a JSON string that represents the hierarchy of the tree"""
    node_list = []
    for folder_name, subfolders in node.iteritems():
      childs_or_leaf = '"children": [' + self.generate_json_from_tree(subfolders) + ']' if subfolders else '"children": []'
      node_list.append('{"id": "%s", "text": "%s", %s}' % (folder_name, folder_name, childs_or_leaf)) 
    return ','.join(node_list)
  
  def place_in_tree(self, node, path):
    """Recursively places the given strings in path inside a tree data structure (that is implemented using dicts)"""
    path_list = path.split('/')
    childnode_name = path_list.pop(0)
    #logging.debug("childnode_name=%s" % childnode_name)
    if not node.has_key(childnode_name):
      node[childnode_name] = {}  #insert a dictionary/map
      
    childnode = node[childnode_name]  
    if len(path_list) > 1:
      self.place_in_tree(childnode, '/'.join(path_list))
    elif len(path_list) == 1:
      leaf_name = path_list.pop(0)
      if not childnode.has_key(leaf_name):    
        childnode[leaf_name] = ''      #leaf doesn't need to be dict since it won't contain anything
                
class GetKeysHandler(MyBaseReqHandler):
  """Return a JSON string/response with all the S3 keys for a given Bucket or virtual path""" 
  def post(self):
    aws_access_key_id = self.request.get('awsAccessKeyId')
    aws_secret_access_key = self.request.get('awsSecretKey')
    aws_model = AWSModel(aws_access_key_id, aws_secret_access_key)
      
    bucket_name = self.request.get('bucket_name')
    vfolder_path = self.request.get('virtual_folder_path')

    if vfolder_path:    
      vfolder_list = vfolder_path.split('/')
      bucket_name = vfolder_list.pop(0)
      vfolder_path = '/'.join(vfolder_list)
    
    #logging.debug('buckname=%s and vfp=%s' % (bucket_name, vfolder_path))
    
    objs = aws_model.get_data("keys", bucket_name)
    json_list = []
    key_list = []
    for obj in objs:
      key_name = obj.key
      file_size = obj.size
      timestamp = obj.last_modified
      ts = time.strptime(timestamp[:19], "%Y-%m-%dT%H:%M:%S")
      last_mod = time.strftime("%m/%d/%Y", ts)  
      if vfolder_path:  #if vfolder_path is defined, it means client is requesting s3fox view
        if key_name.startswith(vfolder_path) and not key_name.endswith('_$folder$'):
          key_name = key_name.replace(vfolder_path + '/', '')
          if key_name.rfind('/') < 0: #if key_name does not describe a subfolder such as grey/foo.png
            key_list.append('{"key": "%s", "fileSize": %s, "lastMod": "%s"}' % (key_name, file_size, last_mod))
      else:
        key_list.append('{"key": "%s", "fileSize": %s, "lastMod": "%s"}' % (key_name, file_size, last_mod))
      #self.dump(obj)
      
    key_list_str = ','.join(key_list)
    json_list.append("{ keys: [")
    json_list.append(key_list_str)
    json_list.append("]}")        
    json_str = ''.join(json_list)
    
    self.response.headers.add_header("Content-Type", 'application/json')
    self.response.out.write(json_str) 
    
class PutS3ObjHandler(MyBaseReqHandler):
  def post(self):
    bucket_name = self.request.get('bucketName')
    path, key_name = os.path.split(self.request.get('keyName'))
    obj = self.request.get('fileData')    
    aws_access_key_id = self.request.get('awsAccessKeyId')
    aws_secret_access_key = self.request.get('awsSecretKey')   
    aws_model = AWSModel(aws_access_key_id, aws_secret_access_key)
    
    if bucket_name and key_name and obj:
      response = aws_model.put_obj(bucket_name, key_name, obj)
      self.response.out.write('{"success": true, "filename": "%s"}' % key_name)
    else:
      logging.debug('Requested /putS3Obj failed to provide all necessary parameters')
      self.response.out.write('Error')
    
class DeleteS3ObjHandler(MyBaseReqHandler):
  def post(self):
    bucket_name = self.request.get('bucketName')
    key_name = self.request.get('keyName')
    aws_access_key_id = self.request.get('awsAccessKeyId')
    aws_secret_access_key = self.request.get('awsSecretKey')   
    aws_model = AWSModel(aws_access_key_id, aws_secret_access_key)
    
    if bucket_name and key_name:
      aws_model.delete(bucket_name, key_name)
      
class DeleteS3ObjsHandler(MyBaseReqHandler):
  def post(self):
    bucket_name = self.request.get('bucketName')
    key_names = self.request.get_all('keyNames')    
    aws_access_key_id = self.request.get('awsAccessKeyId')
    aws_secret_access_key = self.request.get('awsSecretKey')   
    aws_model = AWSModel(aws_access_key_id, aws_secret_access_key)
    
    if bucket_name and key_names:
      aws_model.delete_objs(bucket_name, key_names)


class GetS3ObjHandler(MyBaseReqHandler):
  def get(self):
    aws_access_key_id = self.request.get('awsAccessKeyId')
    aws_secret_access_key = self.request.get('awsSecretKey')  
    s3_gen = S3.QueryStringAuthGenerator(aws_access_key_id, aws_secret_access_key)
    bucket_name = self.request.get('bucketName')
    key_name = self.request.get('keyName')

    if bucket_name and key_name:
      resp = s3_conn.get_acl(bucket_name, key_name).object.data
      #logging.debug('RESPONSE: %s' % resp)
      #self.response.headers.add_header("Content-Type", 'image/png')
      self.response.out.write(resp)
      #memcache.delete(bucket_name+"keys") #flush listing of keys for this bucket to enable refresh
    else:
      self.redirect('/') #return to main page
      
class GetS3ObjUrlHandler(MyBaseReqHandler):
  def post(self):
    aws_access_key_id = self.request.get('awsAccessKeyId')
    aws_secret_access_key = self.request.get('awsSecretKey')
    bucket_name = self.request.get('bucketName')
    key_name = self.request.get('keyName')
    
    if bucket_name and key_name:
      aws_model = AWSModel(aws_access_key_id, aws_secret_access_key)
      url = aws_model.get_url(bucket_name, key_name)
      self.response.headers.add_header("Content-Type", 'application/json')
      self.response.out.write('{ "url": "%s" }' % url)
    else:
      self.response.out.write('') 
